import { EnumSalaryType, EnumWorkMode, type JobAddressResult, type JobDetailResult, type JobEditStep1Request } from "@/api/siderBar/model"
import { getSettingGetdepartments, getSettingGetinterviewers } from "@/api/siderBar/setting"
import router from "@/router"
import type { DefaultOptionType } from "ant-design-vue/es/select"
import type { Exposed as WorkAdressModalExposed } from "../components/WorkAdressModal/types"
import { message } from "ant-design-vue"
import { useAppStore, useUserStore } from "@/stores"
import type { RouteParams } from "../types"
import { postJobJobstep1Id } from "@/api/siderBar/job"

interface FormState {
    position?: string
    workMode: EnumWorkMode
    jobType?: [rid: number, pid: number, lid: number]
    salaryMin?: number
    salaryMax?: number
    salaryUnit?: number
    departmentId?: number
    publishUserId?: number
    description?: string
    workAddress?: JobAddressResult
}
interface UseStepOneOptions {
    query: Ref<RouteParams>
    next: IFn
}
export function useStepOne({ query, next }: UseStepOneOptions) {
    const appStore = useAppStore()
    const workAddressRef = ref<WorkAdressModalExposed>()
    const loadingStepOne = ref(false)
    const salaryFullOptions = createSalaryOptions()
    const salaryHourMinOptions = createSalaryHourOptions()
    const salaryHourMaxOptions = salaryHourMinOptions.slice(1).concat({value: 5000,label: '5000'})
    const salaryDayMinOptions = createSalaryDayOptions()
    const salaryDayMaxOptions = salaryDayMinOptions.slice(1).concat({value: 10000,label: '10000'})
    const salaryWeekMinOptions = createSalaryWeekOptions()
    const salaryWeekMaxOptions = salaryWeekMinOptions.slice(1).concat({value: 50000,label: '50000'})
    const salaryMonthMinOptions = createSalaryMonthOptions()
    const salaryMonthMaxOptions = salaryMonthMinOptions.slice(1).concat({value: 260000,label: '260000'})
    const salarySemiOptionMap = new Map<EnumSalaryType, {min: IOption<number>[]; max: IOption<number>[]}>([
        [EnumSalaryType.时薪, { min: salaryHourMinOptions, max: salaryHourMaxOptions }],
        [EnumSalaryType.日薪, { min: salaryDayMinOptions, max:salaryDayMaxOptions }],
        [EnumSalaryType.周薪, { min: salaryWeekMinOptions, max: salaryWeekMaxOptions }],
        [EnumSalaryType.月薪, { min: salaryMonthMinOptions, max: salaryMonthMaxOptions }]
    ])
    const salaryOptions = computed(() => {
        let min: IOption<number>[] = []
        let max: IOption<number>[] = []
        const { workMode, salaryUnit } = formState.value
        if (workMode === EnumWorkMode.全职) {
            min = max = salaryFullOptions
        } else if (isSetValue(salaryUnit)) {
            ;({ min, max } = salarySemiOptionMap.get(salaryUnit)!)
        }
        return {
            min,
            max
        }
    })
    const workModeFullOptions: IOption<number>[] = Array.from({ length: 12 }).map((_, i) => ({ value: i + 12, label: i + 12 + '个月' }))
    const workModeSemiOptions: IOption<EnumSalaryType>[] = [
        { value: EnumSalaryType.时薪, label: '元/时' },
        { value: EnumSalaryType.日薪, label: '元/天' },
        { value: EnumSalaryType.周薪, label: '元/周' },
        { value: EnumSalaryType.月薪, label: '元/月' }
    ]
    const formState = ref(getInitialState())
    const { cascadeJobTypes, refreshAsync } = useFetchJobTypes()
    const { data: departmentOptions } = useRequest(() => getSettingGetdepartments(), { initialData: [] })
    const { data: publishUserOptions, loading: publishUserLoading, runAsync } = useRequest(() => getSettingGetinterviewers({}), { initialData: [] })
    const salaryUnitOptions = computed(() => {
        if (formState.value.workMode === EnumWorkMode.全职) {
            return workModeFullOptions
        } else {
            return workModeSemiOptions
        }
    })
    const inputAddress = computed(() => {
        const { workAddress } = formState.value
        if (workAddress) {
            return `${workAddress.regionName}${workAddress.address}`
        }
        return ""
    })
    function getInitialState(): FormState {
        return {
            workMode: EnumWorkMode.全职,
            publishUserId: useUserStore().userInfo?.id
        }
    }
    function createSalaryHourOptions(): IOption<number>[] {
        const small: IOption<number>[] = []
        for (let i = 5; i <= 100; i+=5) {
            small.push({
                value: i,
                label: `${i}`
            })
        }
        const medium: IOption<number>[] = [{ value: 120, label: '120' }]
        const large: IOption<number>[] = []
        for (let i = 150; i <= 1000; i+=50) {
            large.push({
                value: i,
                label: `${i}`
            })
        }
        const largest: IOption<number>[] = []
        for (let i = 1100; i <= 4900; i+=100) {
            large.push({
                value: i,
                label: `${i}`
            })
        }
        return [
            ...small,
            ...medium,
            ...large,
            ...largest
        ]
    }
    function createSalaryDayOptions(): IOption<number>[] {
        const small: IOption<number>[] = []
        for (let i = 50; i <= 300; i+=10) {
            small.push({
                value: i,
                label: `${i}`
            })
        }
        const medium: IOption<number>[] = [{ value: 320, label: '320' }]
        const large: IOption<number>[] = []
        for (let i = 350; i <= 1000; i+=50) {
            large.push({
                value: i,
                label: `${i}`
            })
        }
        const largest: IOption<number>[] = []
        for (let i = 1100; i <= 9900; i+=100) {
            large.push({
                value: i,
                label: `${i}`
            })
        }
        return [
            ...small,
            ...medium,
            ...large,
            ...largest
        ]
    }
    function createSalaryWeekOptions(): IOption<number>[] {
        const small: IOption<number>[] = []
        for (let i = 100; i <= 1000; i+=100) {
            small.push({
                value: i,
                label: `${i}`
            })
        }
        const medium: IOption<number>[] = []
        for (let i = 1200; i <= 2100; i+=300) {
            medium.push({
                value: i,
                label: `${i}`
            })
        }
        const large: IOption<number>[] = []
        for (let i = 2500; i <= 10000; i+=500) {
            large.push({
                value: i,
                label: `${i}`
            })
        }
        const largest: IOption<number>[] = []
        for (let i = 11000; i <= 49000; i+=1000) {
            large.push({
                value: i,
                label: `${i}`
            })
        }
        return [
            ...small,
            ...medium,
            ...large,
            ...largest
        ]
    }
    function createSalaryMonthOptions(): IOption<number>[] {
        const small: IOption<number>[] = []
        for (let i = 500; i <= 10000; i+=500) {
            small.push({
                value: i,
                label: `${i}`
            })
        }
        const medium: IOption<number>[] = []
        for (let i = 11000; i <= 30000; i+=1000) {
            medium.push({
                value: i,
                label: `${i}`
            })
        }
        const large: IOption<number>[] = []
        for (let i = 35000; i <= 100000; i+=5000) {
            large.push({
                value: i,
                label: `${i}`
            })
        }
        const largest: IOption<number>[] = []
        for (let i = 110000; i <= 250000; i+=10000) {
            large.push({
                value: i,
                label: `${i}`
            })
        }
        return [
            ...small,
            ...medium,
            ...large,
            ...largest
        ]
    }
    function createSalaryOptions(): IOption<number>[] {
        const low = Array.from({length: 30}).map<IOption<number>>((_, i) => ({ value: i + 1, label: i + 1 + 'k' }))
        const medium: IOption<number>[] = []
        for (let i = 35; i <= 100; i += 5) {
            medium.push({ value: i, label: i + 'k' })
        }
        const top: IOption<number>[] = []
        for (let i = 110; i <= 250; i += 10) {
            top.push({ value: i, label: i + 'k' })
        }
        return [
            ...low,
            ...medium,
            ...top
        ]
    }
    function getPositionOptions(text: string): Promise<DefaultOptionType[]> {
        return new Promise(resolve => {
            text = text.trim()
            if (!text) return resolve([])
            return resolve(cascadeJobTypes.value.leafGroup.filter(l => l.name.match(new RegExp(text, 'i'))))   
        })
    }
    function handlePositionChange(_: number, option: CascadeJobTypesOption) {
        if (option) {
            formState.value.position = option.label
            formState.value.description = option.introduction
            const parent = cascadeJobTypes.value.parentGroup.find(l => l.id === option.parentId)
            const rid = cascadeJobTypes.value.rootGroup.find(l => l.id === parent?.parentId)!.id
            formState.value.jobType = [rid, parent!.id, option.id]
        }
    }
    function handleWorkModeChange() {
        formState.value.salaryMin = formState.value.salaryMax
        if (formState.value.workMode === EnumWorkMode.全职) {
            formState.value.salaryUnit = void 0
        } else {
            formState.value.salaryUnit = EnumSalaryType.时薪
        }
    }
    function triggerWorkAddress() {
        if (workAddressRef.value) {
            workAddressRef.value.open(formState.value.workAddress)
        }
    }
    function handleCancelStepOne() {
        router.back()
    }
    function receiveWorkAddress(address: JobAddressResult) {
        formState.value.workAddress = address
    }
    async function handleConfirmStepOne() {
        // validation & collection
        const params = validateAndCollect()
        if (!params) return
        // submition
        try {
            appStore.toggleLoading(true)
            const id = await postJobJobstep1Id(Number(query.value.id || 0), params)
            appStore.toggleLoading(false)
            message.success('保存成功')
            if (isSetValue(id)) {
                query.value.id = String(id)
            }
            next()
        } catch (error) {
            console.log(error)
            appStore.toggleLoading(false)
        }
    }
    function validateAndCollect() {
        const state = formState.value
        const params = <JobEditStep1Request>{}
        const position = state.position?.trim()
        if (!position) {
            message.error('请输入职位名称')
            return false
        }
        params.name = position
        params.workMode = state.workMode
        if (!state.jobType || state.jobType.length <= 0) {
            message.error('请选择职位类别')
            return false
        }
        const [,,jobTypeId] = state.jobType
        params.jobTypeId = jobTypeId
        if (state.salaryMin && state.salaryMax && isSetValue(state.salaryUnit)) {
            params.salaryMin = state.salaryMin
            params.salaryMax = state.salaryMax
            if (state.workMode === EnumWorkMode.全职) {
                params.salaryCount = state.salaryUnit
            } else {
                params.salaryType = state.salaryUnit
            }
        } else {
            message.error('请选择薪资范围')
            return
        }
        if (!state.departmentId) {
            message.error('请选择所属部门')
            return false
        }
        params.departmentId = state.departmentId
        if (!state.publishUserId) {
            message.error('请选择招聘HR')
            return false
        }
        params.publishUserId = state.publishUserId
        if (!state.workAddress) {
            message.error('请选择工作地点')
            return false
        }
        params.jobAddressId = state.workAddress.id
        const description = state.description?.trim()
        if (!description) {
            message.error('请输入职位描述')
            return false
        }
        params.responsibility = description
        return params 
    }
    async function populateDetail(detail:JobDetailResult) {
        if (!detail) return
        if (detail.name) formState.value.position = detail.name
        if (isSetValue(detail.workMode)) {
            formState.value.workMode = detail.workMode
            if (isSetValue(detail.salaryCount) || isSetValue(detail.salaryType)) {
                formState.value.salaryUnit = formState.value.workMode === EnumWorkMode.全职 ? detail.salaryCount : detail.salaryType
            }
        }
        if (isSetValue(detail.jobTypeId)) {
            await refreshAsync()
            nextTick(() => {
                const leaf = cascadeJobTypes.value.leafGroup.find(l => l.value === detail.jobTypeId)
                if (leaf) {
                    const p = cascadeJobTypes.value.parentGroup.find(l => l.value === leaf.parentId)
                    if (p) {
                        const r = cascadeJobTypes.value.rootGroup.find(l => l.value === p.parentId)
                        if (r) {
                            formState.value.jobType = [r.value, p.value, leaf.value]
                        }
                    }
                }
            })
        }
        if (isSetValue(detail.salaryMin)) formState.value.salaryMin = detail.salaryMin
        if (isSetValue(detail.salaryMax)) formState.value.salaryMax = detail.salaryMax
        if (isSetValue(detail.departmentId)) {formState.value.departmentId = detail.departmentId; runAsync()}
        if (isSetValue(detail.publishUserId)) formState.value.publishUserId = detail.publishUserId
        if (detail.workAddress) formState.value.workAddress = detail.workAddress
        if (isSetValue(detail.responsibility)) formState.value.description = detail.responsibility
    }
    return {
        formState,
        inputAddress,
        cascadeJobTypes,
        salaryOptions,
        salaryUnitOptions,
        departmentOptions,
        publishUserOptions,
        publishUserLoading,
        loadingStepOne,
        workAddressRef,
        triggerWorkAddress,
        receiveWorkAddress,
        getPositionOptions,
        handlePositionChange,
        handleWorkModeChange,
        handleCancelStepOne,
        handleConfirmStepOne,
        populateDetail
    }
}